package com.netcracker.training.automonic.parser;

import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

import com.netcracker.training.automonic.dao.entities.Attribute;
import com.netcracker.training.automonic.dao.entities.AttributeType;
import com.netcracker.training.automonic.dao.entities.Object;
import com.netcracker.training.automonic.dao.entities.Site;
import com.netcracker.training.automonic.dao.entities.Statistics;
import com.netcracker.training.automonic.dao.entities.StatsType;
import com.netcracker.training.automonic.dao.factories.DAOFactory;
import com.netcracker.training.automonic.dao.roles.ReadWriteDAO;
import com.netcracker.training.automonic.dao.roles.WriteDAO;

/**
 * Parse data from table on <a
 * href="http://finviz.com/screener.ashx">Finviz.com</a>
 * 
 * @author lester
 * 
 */
public class FinvizParser extends JsoupParser implements IParser {

	// Indexes from table at Finviz.com/screener
	private static final int START_COL_NUM = 2;
	private static final int MID_COL_NUM = 5;
	private static final int LAST_COL_NUM = 10;

	private static final String HOME_PAGE = "http://finviz.com/";
	private static final String TABLE_PAGE = "screener.ashx";

	private static final String NEXT_BUTTON_CSS_QUERY = "a[class=tab-link]:contains(next)";
	private static final String PROPERTIES_CSS_QUERY = "td[class^=table-top]";
	private static final String ROWS_CSS_QUERY = "tr[class^=table-]";

	private ReadWriteDAO rwDao;
	private Site site;
	private List<Object> objects;
	private List<Attribute> attributes;
	private List<Statistics> statistics;
	private List<AttributeType> attrTypes;
	private List<StatsType> statsTypes;

	private Elements properties;

	public FinvizParser(DAOFactory daoFactory) {
		super.daoFactory = daoFactory;
	}

	public void init() {
		rwDao = daoFactory.getReadWriteDAO();
		site = getSite();
		doc = getDocumentByConnect(HOME_PAGE + TABLE_PAGE);

	}

	public void parseObjects() {
		objects = new ArrayList<Object>();
		attributes = new ArrayList<Attribute>();
		attrTypes = parseAttributeTypes();
		parseDataFromTable(START_COL_NUM, MID_COL_NUM);
	}

	public void parseStatistics() {
		statistics = new ArrayList<Statistics>();
		objects = rwDao.selectAllObjects();
		statsTypes = parseStatsTypes();
		parseDataFromTable(MID_COL_NUM + 1, LAST_COL_NUM);
	}

	public List<Object> getParsedObjects() {
		return objects == null ? Collections.EMPTY_LIST : objects;
	}

	public List<Statistics> getParsedStatistics() {
		return statistics == null ? Collections.EMPTY_LIST : statistics;
	}

	private void parseDataFromTable(int firstColumnIndex, int lastColumnIndex) {
		while (doc != null) {
			Elements rows = doc.select(ROWS_CSS_QUERY);
			for (Element row : rows) {
				Elements values = row.getElementsByClass("body-table-nw");
				String companyTicker = values.get(1).text();
				Object company = rwDao.selectObjectBySiteAndName(getSite(),
						companyTicker);
				if (company == null) {
					company = rwDao.createObject(getSite(), companyTicker);
					company.save();
					objects.add(company);
				}
				if (isObjectsParsing(firstColumnIndex)) {

					for (int i = firstColumnIndex; i <= lastColumnIndex; i++) {
						Attribute attr = rwDao.createAttribute(company,
								attrTypes.get(i - firstColumnIndex));
						attr.setValue(values.get(i).text());
						attr.save();
						attributes.add(attr);
					}

				} else {
					for (int i = firstColumnIndex; i <= lastColumnIndex; i++) {
						Statistics stat = rwDao.createStatistics(company,
								statsTypes.get(i - firstColumnIndex));
						stat.setValue(values.get(i).text());
						stat.save();
						statistics.add(stat);
					}
				}

			}
			doc = getNextPage(NEXT_BUTTON_CSS_QUERY, HOME_PAGE);
		}
	}

	private List<AttributeType> parseAttributeTypes() {
		List<AttributeType> attributeTypes = new ArrayList<AttributeType>();
		for (int i = START_COL_NUM; i <= MID_COL_NUM; i++) {
			AttributeType attrType = rwDao.createAttributeType(getProperties()
					.get(i).text().substring(0, 3), getProperties().get(i)
					.text());
			AttributeType existingAttrType = rwDao
					.selectAttributeTypeByCode(attrType.getCode());
			if (existingAttrType == null) {
				attrType.save();
				attributeTypes.add(attrType);
			} else
				attributeTypes.add(existingAttrType);
		}
		return attributeTypes;
	}

	private List<StatsType> parseStatsTypes() {
		List<StatsType> statsTypes = new ArrayList<StatsType>();
		for (int i = MID_COL_NUM + 1; i <= LAST_COL_NUM; i++) {
			StatsType statsType = rwDao.createStatsType(getProperties().get(i)
					.text().substring(0, 3), getProperties().get(i).text());
			StatsType existingStatType = rwDao.selectStatsTypeByCode(statsType
					.getCode());
			if (existingStatType == null) {
				statsType.save();
				statsTypes.add(statsType);
			} else
				statsTypes.add(existingStatType);
		}
		return statsTypes;
	}

	private Site getSite() {
		if (site == null) {
			if (rwDao.selectSiteByName(HOME_PAGE) == null) {
				site = rwDao.createSite(HOME_PAGE);
				site.save();
			} else
				site = rwDao.selectSiteByName(HOME_PAGE);
		}
		return site;
	}

	private Elements getProperties() {
		if (properties == null)
			properties = doc.select(PROPERTIES_CSS_QUERY);
		return properties;
	}

	private boolean isObjectsParsing(int firstColumnIndex) {
		if (firstColumnIndex == START_COL_NUM)
			return true;
		else
			return false;
	}

}
